#include <linux/init.h> /* Needed for the macros */
#include <linux/kernel.h> /* Needed for pr_info() */
#include <linux/module.h> /* Needed by all modules */
#include <linux/i2c.h>
#include <linux/iio/iio.h>

/**
 *

pressure@78 {
	compatible = "mychipt";
	reg = <0x78>;
	};



 https://www.linuxjournal.com/search/node?keys=input+subsystem



 There are two ways for a user space application to interact with an IIO driver.

 /sys/bus/iio/iio:deviceX/, this represents a hardware sensor and groups together the data channels of the same chip.
 /dev/iio:deviceX, character device node interface used for buffered data transfer and for events information retrieval.




 Available standard attributes for IIO devices are described in the Documentation/ABI/testing/sysfs-bus-iio file in the Linux kernel sources.

 https://bootlin.com/blog/the-backbone-of-a-linux-industrial-i-o-driver/

 https://www.kernel.org/doc/html/v4.12/driver-api/iio/intro.html


 There are two ways for a user space application to interact with an IIO driver.

 /sys/bus/iio/iio:deviceX/, this represents a hardware sensor and groups together the data channels of the same chip.
 /dev/iio:deviceX, character device node interface used for buffered data transfer and for events information retrieval.


 /sys/bus/iio/devices/iio:device2


 */

struct iio_dev *myiio;

/**
 * function to request a value from the device. mask specifies which value. Note 0 means a reading of the channel in question.
 * Return value will specify the type of value returned by the device. val and val2 will contain the elements making up the returned value.
 *
 *
 */
int myiio_readraw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
		int *val, int *val2, long mask) {
	pr_info("myiio_readraw start\n");
	pr_info("myiio_readraw: iio_dev.name = %s\n", indio_dev->name);
	pr_info("myiio_readraw: iio_dev.type = %d\n", chan->type);
	pr_info("myiio_readraw: mask = %ld", mask);

	pr_info("channel= %d", chan->channel);

	switch (chan->channel) {
	case 1:
		*val = 365;
			*val2 = 10;
			return IIO_VAL_FRACTIONAL;
		break;
	case 2:
		*val = 892;
			*val2 = 10;
			return IIO_VAL_FRACTIONAL;
		break;
	default:
		return 0;
		break;
	}

}

static const struct iio_chan_spec temp_channel[] = {
		{
		.type = IIO_TEMP,
		.indexed =1 ,
		.channel=1,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
		},
		{
		.type = IIO_TEMP,
		.indexed =1 ,
		.channel=2,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
		},
};

static const struct iio_info info = { .driver_module = THIS_MODULE, .read_raw =
		myiio_readraw, };

int myprobe(struct i2c_client *client, const struct i2c_device_id *id) {
	pr_info("probe\n");
	pr_err("name: = %s \n", client->name);
	pr_err("name: = 0x%x  \n", client->addr);
	pr_err("i2c_device_id: = %s  \n", id->name);

	myiio = devm_iio_device_alloc(&client->dev, sizeof(*myiio));
	myiio->channels = temp_channel;
	myiio->num_channels = ARRAY_SIZE(temp_channel);
	myiio->name = "myiio1025";
	myiio->dev.parent = &client->dev;
	myiio->info = &info;
	myiio->modes = INDIO_DIRECT_MODE;
	return devm_iio_device_register(&client->dev, myiio);
}

int myremove(struct i2c_client *client) {
	pr_info("remove\n");
	devm_iio_device_unregister(&client->dev, myiio);
	iio_device_free(myiio);
	return 0;
}

static const struct i2c_device_id my_i2c_id[] = { { "mychipt", 0 }, { }, };

static struct i2c_driver my_i2c_driver = { .driver =
		{ .name = "my_i2c_driver", }, .probe = myprobe, .id_table = my_i2c_id,
		.remove = myremove, };

static int __init foo_init(void)
{
	pr_info("init my_i2c_driver\n");
return i2c_add_driver(&my_i2c_driver);
}

static void __exit foo_cleanup(void)
{
	i2c_del_driver(&my_i2c_driver);
}

module_init(foo_init);
module_exit(foo_cleanup);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Andy");
MODULE_DESCRIPTION("andy one-key driver");
MODULE_ALIAS("one-key");
